package com.ys168.gam.view;

import java.awt.Color;
import java.awt.Component;
import java.awt.FlowLayout;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.Toolkit;
import java.awt.datatransfer.StringSelection;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.File;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;

import javax.swing.AbstractButton;
import javax.swing.ButtonGroup;
import javax.swing.DefaultComboBoxModel;
import javax.swing.DefaultListModel;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JProgressBar;
import javax.swing.JRadioButton;
import javax.swing.JScrollPane;
import javax.swing.JSeparator;
import javax.swing.JSlider;
import javax.swing.JSpinner;
import javax.swing.JTabbedPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.JToolBar;
import javax.swing.SpinnerNumberModel;
import javax.swing.SwingConstants;
import javax.swing.UIManager;
import javax.swing.border.EmptyBorder;
import javax.swing.border.TitledBorder;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;

import com.ys168.gam.bean.EngineInfo;
import com.ys168.gam.bean.JobInfo;
import com.ys168.gam.bean.SearchConditionInfo;
import com.ys168.gam.bean.TypeInfo;
import com.ys168.gam.component.JKListCellRender;
import com.ys168.gam.component.JKRadioModel;
import com.ys168.gam.download.DownloadEvent;
import com.ys168.gam.download.DownloadStatus;
import com.ys168.gam.download.Downloader;
import com.ys168.gam.download.IDownloadListener;
import com.ys168.gam.searcher.SearcherFactory;
import com.ys168.gam.util.ConfigLoader;
import com.ys168.gam.util.ResourceLoader;

/**
 * 
 * @author Jason Krebs
 * @since 2015年6月8日
 */
public class MainFrame extends JFrame {

    private static final long serialVersionUID = 2094914817025543674L;

    private static void addPopup(Component component, final JPopupMenu popup) {
        component.addMouseListener(new MouseAdapter() {
            public void mousePressed(MouseEvent e) {
                if (e.isPopupTrigger()) {
                    showMenu(e);
                }
            }

            public void mouseReleased(MouseEvent e) {
                if (e.isPopupTrigger()) {
                    showMenu(e);
                }
            }

            private void showMenu(MouseEvent e) {
                popup.show(e.getComponent(), e.getX(), e.getY());
            }
        });
    }

    private ButtonGroup engineGroup;
    private JButton downloadButton;
    private JButton clearButton;
    private JButton searchButton;

    private JButton saveDirectoryButton;

    private JComboBox pictureSizeCombobox;
    private JLabel threadCountTip;
    private JLabel successedCountLabel;
    private JLabel failedCountLabel;

    private JList pictureList;
    private JPanel contentPane;

    private JProgressBar progressBar;
    private JSlider threadCountSlider;
    private JSpinner heightSpinner;
    private JSpinner widthSpinner;
    private JSpinner pictureCountSpinner;

    private JSpinner startPageIndexSpinner;
    private JTextArea logTextArea;
    private JTextArea helpTextArea;
    private JTextField wordTextField;

    private JTextField saveDirectoryTextField;

    private JMenuItem copySelectedItem;

    private Timer searchingTimer;
    private Timer downloadingTimer;
    private int searchingCostTimeInSeconds;
    private int downloadingCostTimeInSeconds;

    /**
     * Create the frame.
     */
    public MainFrame() {
        setTitle("美图嗅嗅");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setBounds(0, 0, 550, 550);
        contentPane = new JPanel();
        contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
        setContentPane(contentPane);
        GridBagLayout gbl_contentPane = new GridBagLayout();
        gbl_contentPane.columnWeights = new double[] { 1.0, 1.0, 0.0 };
        gbl_contentPane.rowWeights = new double[] { 0.0, 0.0, 1.0, 0.0 };
        contentPane.setLayout(gbl_contentPane);

        createContentSearchPanel();
        createSearchFilterPanel();
        createButtonPanel();
        createDetailTabPane();
        createPopupMenu();

        // enabledUI(false);

        addListener();
    }

    private void addListener() {
        searchButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                onSearch();
            }
        });
        clearButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                onClear();
            }
        });
        wordTextField.addKeyListener(new KeyAdapter() {
            @Override
            public void keyReleased(KeyEvent e) {
                searchButton.setEnabled(!wordTextField.getText().trim().isEmpty());
            }
        });
        downloadButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent arg0) {
                onDownload();
            }
        });
        threadCountSlider.addChangeListener(new ChangeListener() {
            @Override
            public void stateChanged(ChangeEvent e) {
                threadCountTip.setText(threadCountSlider.getValue() + "/" + threadCountSlider.getMaximum());
            }
        });
        pictureCountSpinner.addChangeListener(new ChangeListener() {
            @Override
            public void stateChanged(ChangeEvent arg0) {
                SpinnerNumberModel model = (SpinnerNumberModel) pictureCountSpinner.getModel();
                progressBar.setMaximum((Integer) model.getValue());
            }
        });
        saveDirectoryButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                setSavePath();
            }
        });

        Enumeration<AbstractButton> engines = engineGroup.getElements();
        while (engines.hasMoreElements()) {
            final JRadioButton radio = (JRadioButton) engines.nextElement();
            final JKRadioModel radioModel = (JKRadioModel) radio.getModel();

            radioModel.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    if (radioModel.isSelected()) {
                        EngineInfo engineInfo = ConfigLoader.getEngineInfo(radioModel.getCode());
                        List<TypeInfo> data = engineInfo.getImageSizeData();
                        pictureSizeCombobox.setModel(new DefaultComboBoxModel(data.toArray()));

                        widthSpinner.setEnabled(false);
                        heightSpinner.setEnabled(false);
                    }
                }
            });
        }
        if (engineGroup.getElements().hasMoreElements()) {
            engineGroup.getElements().nextElement().doClick();
        }
        pictureSizeCombobox.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                JKRadioModel model = (JKRadioModel) engineGroup.getSelection();
                EngineInfo engineInfo = ConfigLoader.getEngineInfo(model.getCode());

                TypeInfo selected = (TypeInfo) pictureSizeCombobox.getSelectedItem();
                boolean enabled = engineInfo.isCustomImageSize() && selected.getCode().isEmpty();

                widthSpinner.setEnabled(enabled);
                heightSpinner.setEnabled(enabled);
            }
        });
        pictureList.addListSelectionListener(new ListSelectionListener() {
            @Override
            public void valueChanged(ListSelectionEvent e) {
                copySelectedItem.setEnabled(!pictureList.getSelectedValuesList().isEmpty());
            }
        });
    }

    private SearchConditionInfo buildSearchCondition() {
        SearchConditionInfo conditionInfo = new SearchConditionInfo();

        String word = wordTextField.getText().trim();
        conditionInfo.setWord(ResourceLoader.encodeWord(word));
        conditionInfo.setDownloadSize((Integer) pictureCountSpinner.getValue());

        DefaultComboBoxModel model = (DefaultComboBoxModel) pictureSizeCombobox.getModel();
        TypeInfo selected = (TypeInfo) model.getSelectedItem();
        conditionInfo.setImageSizeCode(selected.getCode());

        conditionInfo.setStartPageIndex((Integer) startPageIndexSpinner.getValue());

        if (selected.getCode().isEmpty()) {
            conditionInfo.setWidth((Integer) widthSpinner.getValue());
            conditionInfo.setHeight((Integer) heightSpinner.getValue());
        }

        return conditionInfo;
    }

    @SuppressWarnings("unchecked")
    private void copyToClipboard() {
        StringBuilder sb = new StringBuilder();
        int count = 0;
        for (JobInfo jobInfo : (List<JobInfo>) pictureList.getSelectedValuesList()) {
            sb.append(jobInfo.getUrl().toString()).append("\r\n");
            count++;
        }
        StringSelection stsel = new StringSelection(sb.toString());
        Toolkit.getDefaultToolkit().getSystemClipboard().setContents(stsel, stsel);

        JOptionPane.showMessageDialog(this, "成功复制" + count + "条链接到剪贴板");
    }

    private void createButtonPanel() {
        JPanel buttonPanel = new JPanel();
        GridBagConstraints gbc_buttonPanel = new GridBagConstraints();
        gbc_buttonPanel.anchor = GridBagConstraints.SOUTH;
        gbc_buttonPanel.insets = new Insets(0, 0, 5, 0);
        gbc_buttonPanel.gridx = 2;
        gbc_buttonPanel.gridy = 1;
        contentPane.add(buttonPanel, gbc_buttonPanel);
        buttonPanel.setBorder(new TitledBorder(null, "", TitledBorder.LEADING, TitledBorder.TOP, null, null));
        GridBagLayout gbl_buttonPanel = new GridBagLayout();
        gbl_buttonPanel.columnWidths = new int[] { 0, 0 };
        gbl_buttonPanel.rowHeights = new int[] { 0, 0, 0 };
        gbl_buttonPanel.columnWeights = new double[] { 0.0, Double.MIN_VALUE };
        gbl_buttonPanel.rowWeights = new double[] { 0.0, 0.0, Double.MIN_VALUE };
        buttonPanel.setLayout(gbl_buttonPanel);

        downloadButton = new JButton("下载");
        GridBagConstraints gbc_downloadButton = new GridBagConstraints();
        gbc_downloadButton.fill = GridBagConstraints.HORIZONTAL;
        gbc_downloadButton.insets = new Insets(0, 0, 5, 0);
        gbc_downloadButton.gridx = 0;
        gbc_downloadButton.gridy = 0;
        buttonPanel.add(downloadButton, gbc_downloadButton);

        clearButton = new JButton("清空");
        GridBagConstraints gbc_clearButton = new GridBagConstraints();
        gbc_clearButton.fill = GridBagConstraints.HORIZONTAL;
        gbc_clearButton.gridx = 0;
        gbc_clearButton.gridy = 1;
        buttonPanel.add(clearButton, gbc_clearButton);
    }

    private void createContentSearchPanel() {
        JPanel contentSearchPanel = new JPanel();
        contentSearchPanel.setBorder(new TitledBorder(UIManager.getBorder("TitledBorder.border"), "内容搜索",
                TitledBorder.LEADING, TitledBorder.TOP, null, new Color(0, 0, 0)));
        GridBagConstraints gbc_contentSearchPanel = new GridBagConstraints();
        gbc_contentSearchPanel.gridwidth = 3;
        gbc_contentSearchPanel.insets = new Insets(0, 0, 5, 0);
        gbc_contentSearchPanel.fill = GridBagConstraints.BOTH;
        gbc_contentSearchPanel.gridx = 0;
        gbc_contentSearchPanel.gridy = 0;
        contentPane.add(contentSearchPanel, gbc_contentSearchPanel);
        GridBagLayout gbl_contentSearchPanel = new GridBagLayout();
        gbl_contentSearchPanel.columnWeights = new double[] { 0.0, 1.0, 0.0 };
        gbl_contentSearchPanel.rowWeights = new double[] { 0.0, 0.0 };
        contentSearchPanel.setLayout(gbl_contentSearchPanel);

        JLabel engineSelectLabel = new JLabel("引擎选择:");
        GridBagConstraints gbc_engineSelectLabel = new GridBagConstraints();
        gbc_engineSelectLabel.anchor = GridBagConstraints.WEST;
        gbc_engineSelectLabel.insets = new Insets(0, 0, 5, 5);
        gbc_engineSelectLabel.gridx = 0;
        gbc_engineSelectLabel.gridy = 0;
        contentSearchPanel.add(engineSelectLabel, gbc_engineSelectLabel);

        JPanel enginePanel = new JPanel();
        GridBagConstraints gbc_enginePanel = new GridBagConstraints();
        gbc_enginePanel.anchor = GridBagConstraints.WEST;
        gbc_enginePanel.insets = new Insets(0, 0, 5, 5);
        gbc_enginePanel.gridx = 1;
        gbc_enginePanel.gridy = 0;
        contentSearchPanel.add(enginePanel, gbc_enginePanel);
        enginePanel.setLayout(new FlowLayout(FlowLayout.CENTER, 5, 5));

        createEngineList(enginePanel);

        searchButton = new JButton("搜索");
        GridBagConstraints gbc_searchButton = new GridBagConstraints();
        gbc_searchButton.fill = GridBagConstraints.VERTICAL;
        gbc_searchButton.gridheight = 2;
        gbc_searchButton.gridx = 2;
        gbc_searchButton.gridy = 0;
        contentSearchPanel.add(searchButton, gbc_searchButton);

        JLabel wordLabel = new JLabel("关键字:");
        GridBagConstraints gbc_wordLabel = new GridBagConstraints();
        gbc_wordLabel.insets = new Insets(0, 0, 0, 5);
        gbc_wordLabel.anchor = GridBagConstraints.WEST;
        gbc_wordLabel.gridx = 0;
        gbc_wordLabel.gridy = 1;
        contentSearchPanel.add(wordLabel, gbc_wordLabel);

        wordTextField = new JTextField();
        wordTextField.setText("游戏壁纸");
        GridBagConstraints gbc_wordTextField = new GridBagConstraints();
        gbc_wordTextField.anchor = GridBagConstraints.NORTH;
        gbc_wordTextField.insets = new Insets(0, 0, 0, 5);
        gbc_wordTextField.fill = GridBagConstraints.HORIZONTAL;
        gbc_wordTextField.gridx = 1;
        gbc_wordTextField.gridy = 1;
        contentSearchPanel.add(wordTextField, gbc_wordTextField);
        wordTextField.setColumns(10);
    }

    private void createDetailTabPane() {
        JTabbedPane detailTabPane = new JTabbedPane(JTabbedPane.TOP);
        GridBagConstraints gbc_tabbedPane = new GridBagConstraints();
        gbc_tabbedPane.insets = new Insets(0, 0, 5, 0);
        gbc_tabbedPane.gridwidth = 3;
        gbc_tabbedPane.fill = GridBagConstraints.BOTH;
        gbc_tabbedPane.gridx = 0;
        gbc_tabbedPane.gridy = 2;
        contentPane.add(detailTabPane, gbc_tabbedPane);

        JScrollPane pictureListScrollPanel = new JScrollPane();
        detailTabPane.addTab("图片列表", null, pictureListScrollPanel, null);

        pictureList = new JList();
        pictureList.setBackground(new Color(211, 211, 211));
        pictureListScrollPanel.setViewportView(pictureList);
        pictureList.setCellRenderer(new JKListCellRender());
        pictureList.setModel(new DefaultListModel());

        JPanel downloadSettingsScrollPanel = new JPanel();
        detailTabPane.addTab("下载设置", null, downloadSettingsScrollPanel, null);
        GridBagLayout gbl_downloadSettingsScrollPanel = new GridBagLayout();
        gbl_downloadSettingsScrollPanel.rowWeights = new double[] { 0.0, 1.0 };
        gbl_downloadSettingsScrollPanel.columnWeights = new double[] { 1.0 };
        downloadSettingsScrollPanel.setLayout(gbl_downloadSettingsScrollPanel);

        JPanel otherSettingsPanel = new JPanel();
        GridBagConstraints gbc_otherSettingsPanel = new GridBagConstraints();
        gbc_otherSettingsPanel.insets = new Insets(0, 0, 5, 0);
        gbc_otherSettingsPanel.fill = GridBagConstraints.BOTH;
        gbc_otherSettingsPanel.gridx = 0;
        gbc_otherSettingsPanel.gridy = 0;
        downloadSettingsScrollPanel.add(otherSettingsPanel, gbc_otherSettingsPanel);
        otherSettingsPanel
                .setBorder(new TitledBorder(null, "其他设置", TitledBorder.LEADING, TitledBorder.TOP, null, null));
        GridBagLayout gbl_otherSettingsPanel = new GridBagLayout();
        gbl_otherSettingsPanel.columnWeights = new double[] { 0.0, 1.0, 0.0 };
        gbl_otherSettingsPanel.rowWeights = new double[] { 0.0, 0.0 };
        otherSettingsPanel.setLayout(gbl_otherSettingsPanel);

        JLabel saveDirectoryLabel = new JLabel("保存目录:");
        GridBagConstraints gbc_saveDirectoryLabel = new GridBagConstraints();
        gbc_saveDirectoryLabel.insets = new Insets(0, 0, 5, 5);
        gbc_saveDirectoryLabel.anchor = GridBagConstraints.EAST;
        gbc_saveDirectoryLabel.gridx = 0;
        gbc_saveDirectoryLabel.gridy = 0;
        otherSettingsPanel.add(saveDirectoryLabel, gbc_saveDirectoryLabel);

        saveDirectoryTextField = new JTextField();
        saveDirectoryTextField.setText("D:\\temp");
        saveDirectoryTextField.setEditable(false);
        GridBagConstraints gbc_saveDirectoryTextField = new GridBagConstraints();
        gbc_saveDirectoryTextField.insets = new Insets(0, 0, 5, 5);
        gbc_saveDirectoryTextField.fill = GridBagConstraints.HORIZONTAL;
        gbc_saveDirectoryTextField.gridx = 1;
        gbc_saveDirectoryTextField.gridy = 0;
        otherSettingsPanel.add(saveDirectoryTextField, gbc_saveDirectoryTextField);
        saveDirectoryTextField.setColumns(10);

        saveDirectoryButton = new JButton("...");
        GridBagConstraints gbc_saveDirectoryButton = new GridBagConstraints();
        gbc_saveDirectoryButton.insets = new Insets(0, 0, 5, 0);
        gbc_saveDirectoryButton.gridx = 2;
        gbc_saveDirectoryButton.gridy = 0;
        otherSettingsPanel.add(saveDirectoryButton, gbc_saveDirectoryButton);

        JLabel threadCountLabel = new JLabel("线程数:");
        GridBagConstraints gbc_threadCountLabel = new GridBagConstraints();
        gbc_threadCountLabel.anchor = GridBagConstraints.WEST;
        gbc_threadCountLabel.insets = new Insets(0, 0, 0, 5);
        gbc_threadCountLabel.gridx = 0;
        gbc_threadCountLabel.gridy = 1;
        otherSettingsPanel.add(threadCountLabel, gbc_threadCountLabel);

        threadCountSlider = new JSlider();
        threadCountSlider.setValue(5);
        threadCountSlider.setPaintLabels(true);
        threadCountSlider.setMinimum(1);
        threadCountSlider.setMaximum(20);
        GridBagConstraints gbc_threadCountSlider = new GridBagConstraints();
        gbc_threadCountSlider.fill = GridBagConstraints.HORIZONTAL;
        gbc_threadCountSlider.insets = new Insets(0, 0, 0, 5);
        gbc_threadCountSlider.gridx = 1;
        gbc_threadCountSlider.gridy = 1;
        otherSettingsPanel.add(threadCountSlider, gbc_threadCountSlider);

        threadCountTip = new JLabel(threadCountSlider.getValue() + "/" + threadCountSlider.getMaximum());
        threadCountTip.setHorizontalAlignment(SwingConstants.LEFT);
        GridBagConstraints gbc_threadCountTip = new GridBagConstraints();
        gbc_threadCountTip.anchor = GridBagConstraints.EAST;
        gbc_threadCountTip.gridx = 2;
        gbc_threadCountTip.gridy = 1;
        otherSettingsPanel.add(threadCountTip, gbc_threadCountTip);

        JPanel advanceSettingsPanel = new JPanel();
        advanceSettingsPanel.setBorder(new TitledBorder(null, "高级设置(可选)", TitledBorder.LEADING, TitledBorder.TOP, null,
                null));
        GridBagConstraints gbc_advanceSettingsPanel = new GridBagConstraints();
        gbc_advanceSettingsPanel.fill = GridBagConstraints.BOTH;
        gbc_advanceSettingsPanel.gridx = 0;
        gbc_advanceSettingsPanel.gridy = 1;
        downloadSettingsScrollPanel.add(advanceSettingsPanel, gbc_advanceSettingsPanel);
        GridBagLayout gbl_advanceSettingsPanel = new GridBagLayout();
        gbl_advanceSettingsPanel.columnWidths = new int[] { 0, 0, 0 };
        gbl_advanceSettingsPanel.rowHeights = new int[] { 0, 0 };
        gbl_advanceSettingsPanel.columnWeights = new double[] { 0.0, 1.0, Double.MIN_VALUE };
        gbl_advanceSettingsPanel.rowWeights = new double[] { 0.0, Double.MIN_VALUE };
        advanceSettingsPanel.setLayout(gbl_advanceSettingsPanel);

        JLabel startPageIndexLabel = new JLabel("起始页:");
        GridBagConstraints gbc_startPageIndexLabel = new GridBagConstraints();
        gbc_startPageIndexLabel.insets = new Insets(0, 0, 0, 5);
        gbc_startPageIndexLabel.gridx = 0;
        gbc_startPageIndexLabel.gridy = 0;
        advanceSettingsPanel.add(startPageIndexLabel, gbc_startPageIndexLabel);

        startPageIndexSpinner = new JSpinner();
        startPageIndexSpinner.setModel(new SpinnerNumberModel(0, 0, 10000, 1));
        GridBagConstraints gbc_startPageIndexSpinner = new GridBagConstraints();
        gbc_startPageIndexSpinner.fill = GridBagConstraints.HORIZONTAL;
        gbc_startPageIndexSpinner.gridx = 1;
        gbc_startPageIndexSpinner.gridy = 0;
        advanceSettingsPanel.add(startPageIndexSpinner, gbc_startPageIndexSpinner);

        JScrollPane logScrollPanel = new JScrollPane();
        detailTabPane.addTab("日志信息", null, logScrollPanel, null);

        logTextArea = new JTextArea();
        logTextArea.setEditable(false);
        logTextArea.setBackground(new Color(211, 211, 211));
        logScrollPanel.setViewportView(logTextArea);

        JScrollPane helpScrollPanel = new JScrollPane();
        detailTabPane.addTab("帮助相关", null, helpScrollPanel, null);

        helpTextArea = new JTextArea();
        helpTextArea.setBackground(new Color(211, 211, 211));
        helpTextArea.setEditable(false);
        helpTextArea.setText(ConfigLoader.getHelpInfo());
        helpScrollPanel.setViewportView(helpTextArea);

        JToolBar toolBar = new JToolBar();
        toolBar.setFloatable(false);
        GridBagConstraints gbc_toolBar = new GridBagConstraints();
        gbc_toolBar.fill = GridBagConstraints.HORIZONTAL;
        gbc_toolBar.gridwidth = 3;
        gbc_toolBar.insets = new Insets(0, 0, 0, 5);
        gbc_toolBar.gridx = 0;
        gbc_toolBar.gridy = 3;
        contentPane.add(toolBar, gbc_toolBar);

        progressBar = new JProgressBar();
        progressBar.setStringPainted(true);

        SpinnerNumberModel picNumberModel = (SpinnerNumberModel) pictureCountSpinner.getModel();
        progressBar.setMaximum((Integer) picNumberModel.getValue());
        toolBar.add(progressBar);

        JSeparator separator = new JSeparator();
        separator.setOrientation(SwingConstants.VERTICAL);
        toolBar.add(separator);

        successedCountLabel = new JLabel("成功:-    ");
        successedCountLabel.setIcon(new ImageIcon(MainFrame.class.getResource("/image/green.gif")));
        successedCountLabel.setForeground(new Color(0, 128, 0));
        toolBar.add(successedCountLabel);

        failedCountLabel = new JLabel("失败:-");
        failedCountLabel.setIcon(new ImageIcon(MainFrame.class.getResource("/image/red.gif")));
        failedCountLabel.setForeground(new Color(255, 0, 0));
        toolBar.add(failedCountLabel);
    }

    /**
     * 创建引擎列表
     * 
     * @param enginePanel
     */
    private void createEngineList(JPanel enginePanel) {
        engineGroup = new ButtonGroup();
        for (String code : ConfigLoader.getEngineCodes()) {
            EngineInfo engineInfo = ConfigLoader.getEngineInfo(code);
            final JRadioButton engineRadio = new JRadioButton(engineInfo.getName());
            engineRadio.setModel(new JKRadioModel(code));
            enginePanel.add(engineRadio);

            engineGroup.add(engineRadio);
        }
    }

    private void createPopupMenu() {
        JPopupMenu popupMenu = new JPopupMenu();
        addPopup(pictureList, popupMenu);

        copySelectedItem = new JMenuItem("复制选中行");
        copySelectedItem.setEnabled(false);
        popupMenu.add(copySelectedItem);

        copySelectedItem.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                copyToClipboard();
            }
        });
    }

    private void createSearchFilterPanel() {
        JPanel searchConditionPanel = new JPanel();
        GridBagConstraints gbc_searchConditionPanel = new GridBagConstraints();
        gbc_searchConditionPanel.gridwidth = 2;
        gbc_searchConditionPanel.fill = GridBagConstraints.HORIZONTAL;
        gbc_searchConditionPanel.insets = new Insets(0, 0, 5, 5);
        gbc_searchConditionPanel.gridx = 0;
        gbc_searchConditionPanel.gridy = 1;
        contentPane.add(searchConditionPanel, gbc_searchConditionPanel);
        searchConditionPanel.setBorder(new TitledBorder(UIManager.getBorder("TitledBorder.border"), "搜索条件",
                TitledBorder.LEADING, TitledBorder.TOP, null, new Color(0, 0, 0)));
        GridBagLayout gbl_searchConditionPanel = new GridBagLayout();
        gbl_searchConditionPanel.columnWidths = new int[] { 0, 0, 0, 0, 0 };
        gbl_searchConditionPanel.rowHeights = new int[] { 0, 0, 0 };
        gbl_searchConditionPanel.columnWeights = new double[] { 0.0, 1.0, 0.0, 1.0, Double.MIN_VALUE };
        gbl_searchConditionPanel.rowWeights = new double[] { 0.0, 0.0, Double.MIN_VALUE };
        searchConditionPanel.setLayout(gbl_searchConditionPanel);

        JLabel pictureCountLabel = new JLabel("图片数:");
        GridBagConstraints gbc_pictureCountLabel = new GridBagConstraints();
        gbc_pictureCountLabel.insets = new Insets(0, 0, 5, 5);
        gbc_pictureCountLabel.gridx = 0;
        gbc_pictureCountLabel.gridy = 0;
        searchConditionPanel.add(pictureCountLabel, gbc_pictureCountLabel);

        pictureCountSpinner = new JSpinner();
        pictureCountSpinner.setModel(new SpinnerNumberModel(20, 1, 500, 1));
        GridBagConstraints gbc_pictureCountSpinner = new GridBagConstraints();
        gbc_pictureCountSpinner.insets = new Insets(0, 0, 5, 5);
        gbc_pictureCountSpinner.fill = GridBagConstraints.HORIZONTAL;
        gbc_pictureCountSpinner.gridx = 1;
        gbc_pictureCountSpinner.gridy = 0;
        searchConditionPanel.add(pictureCountSpinner, gbc_pictureCountSpinner);

        JLabel widthLabel = new JLabel("宽:");
        GridBagConstraints gbc_widthLabel = new GridBagConstraints();
        gbc_widthLabel.anchor = GridBagConstraints.WEST;
        gbc_widthLabel.insets = new Insets(0, 0, 5, 5);
        gbc_widthLabel.gridx = 2;
        gbc_widthLabel.gridy = 0;
        searchConditionPanel.add(widthLabel, gbc_widthLabel);

        widthSpinner = new JSpinner();
        widthSpinner.setEnabled(false);
        GridBagConstraints gbc_widthSpinner = new GridBagConstraints();
        gbc_widthSpinner.fill = GridBagConstraints.HORIZONTAL;
        gbc_widthSpinner.insets = new Insets(0, 0, 5, 0);
        gbc_widthSpinner.gridx = 3;
        gbc_widthSpinner.gridy = 0;
        searchConditionPanel.add(widthSpinner, gbc_widthSpinner);

        JLabel pictureSizeLabel = new JLabel("尺寸:");
        GridBagConstraints gbc_pictureSizeLabel = new GridBagConstraints();
        gbc_pictureSizeLabel.anchor = GridBagConstraints.WEST;
        gbc_pictureSizeLabel.insets = new Insets(0, 0, 0, 5);
        gbc_pictureSizeLabel.gridx = 0;
        gbc_pictureSizeLabel.gridy = 1;
        searchConditionPanel.add(pictureSizeLabel, gbc_pictureSizeLabel);

        pictureSizeCombobox = new JComboBox();
        pictureSizeCombobox.setRenderer(new JKListCellRender());

        GridBagConstraints gbc_pictureSizeCombobox = new GridBagConstraints();
        gbc_pictureSizeCombobox.insets = new Insets(0, 0, 0, 5);
        gbc_pictureSizeCombobox.fill = GridBagConstraints.HORIZONTAL;
        gbc_pictureSizeCombobox.gridx = 1;
        gbc_pictureSizeCombobox.gridy = 1;
        searchConditionPanel.add(pictureSizeCombobox, gbc_pictureSizeCombobox);

        JLabel hightLabel = new JLabel("高:");
        GridBagConstraints gbc_hightLabel = new GridBagConstraints();
        gbc_hightLabel.insets = new Insets(0, 0, 0, 5);
        gbc_hightLabel.anchor = GridBagConstraints.WEST;
        gbc_hightLabel.gridx = 2;
        gbc_hightLabel.gridy = 1;
        searchConditionPanel.add(hightLabel, gbc_hightLabel);

        heightSpinner = new JSpinner();
        heightSpinner.setEnabled(false);
        GridBagConstraints gbc_hightSpinner = new GridBagConstraints();
        gbc_hightSpinner.fill = GridBagConstraints.HORIZONTAL;
        gbc_hightSpinner.gridx = 3;
        gbc_hightSpinner.gridy = 1;
        searchConditionPanel.add(heightSpinner, gbc_hightSpinner);
    }

    private void enabledUI(boolean enabled) {
        searchButton.setEnabled(enabled);
        downloadButton.setEnabled(enabled);
        clearButton.setEnabled(enabled);
        threadCountSlider.setEnabled(enabled);
        saveDirectoryButton.setEnabled(enabled);
        startPageIndexSpinner.setEnabled(enabled);
    }

    private List<JobInfo> getJobs() {
        DefaultListModel model = (DefaultListModel) pictureList.getModel();
        List<JobInfo> jobs = new ArrayList<JobInfo>();

        for (int i = 0; i < model.getSize(); i++) {
            jobs.add((JobInfo) model.get(i));
        }
        return jobs;
    }

    private void onClear() {
        wordTextField.setText("");
        SpinnerNumberModel pictureCountModel = (SpinnerNumberModel) pictureCountSpinner.getModel();
        pictureCountModel.setValue(ConfigLoader.DEFAULT_RESULT_COUNT);
        progressBar.setValue(progressBar.getMinimum());

        reset();
        enabledUI(false);
    }

    private void onDownload() {
        String saveDirectory = saveDirectoryTextField.getText();
        int threadCount = threadCountSlider.getValue();

        {
            setDownloading();

            Downloader downloader = new Downloader(getJobs(), saveDirectory);
            downloader.addListener(new IDownloadListener() {
                @Override
                public void onAllDownloadFinished() {
                    setDownloadFinished();
                }

                @Override
                public void onDownloadFinished(DownloadEvent event) {
                    progressBar.setValue(event.getDownloadFinishedCount());
                    successedCountLabel.setText("成功:" + event.getSuccessedCount() + "    ");
                    failedCountLabel.setText("失败:" + event.getFailedCount());

                    if (event.getMessage() != null) {
                        logTextArea.setText(logTextArea.getText() + "【" + event.getUrl() + "】" + event.getMessage()
                                + "\r\n");
                    }
                    updateJobStatus(event.getIndex(), event.getStatus());
                }

                @Override
                public void onDownloading(DownloadEvent event) {
                    updateJobStatus(event.getIndex(), event.getStatus());
                }
            });

            downloader.start(threadCount);
        }
    }

    private void onSearch() {
        reset();

        Thread t = new Thread(new Runnable() {
            @Override
            public void run() {
                setSearching();
                JKRadioModel engineModel = (JKRadioModel) engineGroup.getSelection();
                String engineCode = engineModel.getCode();

                SearchConditionInfo conditionInfo = buildSearchCondition();
                SearcherFactory searcher = new SearcherFactory(engineCode, conditionInfo);

                List<JobInfo> jobs = new ArrayList<JobInfo>();
                try {
                    jobs.addAll(searcher.search());
                }
                catch (Exception e) {
                    logTextArea.setText(e.getMessage() + "\r\n");
                    e.printStackTrace();
                }
                finally {
                    setSearchFinished(jobs);
                }
            }
        });
        t.setName("SearchThread");
        t.setDaemon(true);
        t.start();
    }

    private void reset() {
        DefaultListModel pictureListModel = (DefaultListModel) pictureList.getModel();
        pictureListModel.clear();

        logTextArea.setText("");

        successedCountLabel.setText("成功:-    ");
        failedCountLabel.setText("失败:-");

        copySelectedItem.setEnabled(false);
    }

    private void setDownloadFinished() {
        downloadButton.setText("下载");
        downloadingTimer.cancel();
        enabledUI(true);

        JOptionPane.showMessageDialog(this, "下载完成！共耗时" + downloadingCostTimeInSeconds + "秒.请注意查看日志信息");
    }

    private void setDownloading() {
        downloadingCostTimeInSeconds = 0;
        downloadingTimer = new Timer("DownloadingTimer", true);
        downloadingTimer.schedule(new TimerTask() {
            @Override
            public void run() {
                downloadingCostTimeInSeconds++;
                downloadButton.setText(downloadingCostTimeInSeconds + "");
            }
        }, 0, 1000);

        enabledUI(false);
    }

    private void setSavePath() {
        JFileChooser jFileChooser = new JFileChooser(new File(saveDirectoryTextField.getText()));
        jFileChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
        jFileChooser.setDialogTitle("设置图片保存目录。。。");
        jFileChooser.setApproveButtonText("设置");

        if (jFileChooser.showOpenDialog(MainFrame.this) == JFileChooser.APPROVE_OPTION) {
            File file = jFileChooser.getSelectedFile();
            saveDirectoryTextField.setText(file.getPath());
        }
    }

    protected void setSearchFinished(List<JobInfo> jobs) {
        DefaultListModel model = new DefaultListModel();
        for (JobInfo job : jobs) {
            model.addElement(job);
        }
        pictureList.setModel(model);

        searchingTimer.cancel();
        searchButton.setText("搜索");
        enabledUI(!jobs.isEmpty());
        wordTextField.setEditable(true);

        if (jobs.isEmpty()) {
            searchButton.setEnabled(true);
        }
    }

    private void setSearching() {
        searchingCostTimeInSeconds = 0;
        searchingTimer = new Timer("SearchingTimer", true);
        searchingTimer.schedule(new TimerTask() {
            @Override
            public void run() {
                searchingCostTimeInSeconds++;
                searchButton.setText(searchingCostTimeInSeconds + "");
            }
        }, 0, 1000);

        enabledUI(false);
        wordTextField.setEditable(false);
    }

    private synchronized void updateJobStatus(int index, DownloadStatus status) {
        DefaultListModel model = (DefaultListModel) pictureList.getModel();
        JobInfo object = (JobInfo) model.elementAt(index);
        object.setStatus(status);

        pictureList.repaint();
    }
}
